package com.example.baseutils;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.util.Log;

import com.example.baseutils.application.BaseApplication;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.regex.Pattern;

import static android.content.ContentValues.TAG;
import static android.content.Context.WIFI_SERVICE;

/**
 * Created by xiaoyuren on 2018/2/27.
 * 项目名称：didano-robot
 * 类描述：网络工具类
 * company：www.didano.cn
 * email：vin.qin@didano.cn
 * 创建时间：2018/2/27 15:13
 */

public class NetUtil {

    private static Context mContext = null;
    private static final String TAG = "NetUtil";
    public static void register(Context context) {
        if (mContext == null) {
            synchronized (NetUtil.class) {
                mContext = context;
            }
        }
    }

    /**
     * 判断网络是否可用，包括wifi、mobile、ethernet等
     *
     * @return
     */
    public static boolean isNetworkConnected() {
        ConnectivityManager manager = (ConnectivityManager) BaseApplication.instance.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
        if (networkInfo != null)
            return networkInfo.isAvailable();
        return false;
    }

    /**
     * 判断wifi是否可用
     *
     * @return
     */
    public static boolean isWifiConnected() {
        ConnectivityManager manager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI)
            return networkInfo.isAvailable();
        return false;
    }

    /**
     * 获取无线网络的IP地址
     *
     * @return
     */
    public static String getIpAddr() {
        String ipAddress = null;
        ConnectivityManager manager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
            WifiManager wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            ipAddress = intToIp(wifiInfo.getIpAddress());//得到IPV4地址
        }
        return ipAddress;
    }

    public static boolean pingState(String address) {
        if (address == null) {
            address = "www.baidu.com";
        }
        boolean result = false;
        try {
            Process process = Runtime.getRuntime().exec(" ping -c 4 -w 200 " + address);
            InputStreamReader r = new InputStreamReader(process.getInputStream());
            LineNumberReader returnData = new LineNumberReader(r);
            String returnMsg = "";
            String line = "";
            while ((line = returnData.readLine()) != null) {
                Log.i(TAG, "line: "+line);
                returnMsg += line;
            }
            if (returnMsg.contains("100% loss")) {
                result = false;
                Log.i(TAG, "与 " + address + " 连接不畅通.");
            } else {
                result = true;
                Log.i(TAG, "与 " + address + " 连接畅通.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 获取连接上的WiFi的一些信息
     *
     * @return 成功返回WiFi信息对象，失败返回null
     */
    public static NetUtil.ConnectedWifiInfo getConnectedWifiInfo() {
        NetUtil.ConnectedWifiInfo wifiInfo = null;
        WifiManager wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(WIFI_SERVICE);
        WifiInfo info = wifiManager.getConnectionInfo();
        DhcpInfo dhcpInfo = wifiManager.getDhcpInfo();
        if (info != null && info.getBSSID() != null) {
            wifiInfo = new NetUtil().new ConnectedWifiInfo();
            wifiInfo.setSsid(info.getSSID());
            wifiInfo.setSpeed(info.getLinkSpeed());
            wifiInfo.setUnits(WifiInfo.LINK_SPEED_UNITS);
            wifiInfo.setStrength(info.getRssi());
            wifiInfo.setDhcpInfo(dhcpInfo);

            if (false) {
                StringBuilder sb = new StringBuilder();
                sb.append("网络信息：");
                sb.append("\nipAddress：" + intToIp(dhcpInfo.ipAddress));
                sb.append("\nnetmask：" + intToIp(dhcpInfo.netmask));
                sb.append("\ngateway：" + intToIp(dhcpInfo.gateway));
                sb.append("\nserverAddress：" + intToIp(dhcpInfo.serverAddress));
                sb.append("\ndns1：" + intToIp(dhcpInfo.dns1));
                sb.append("\ndns2：" + intToIp(dhcpInfo.dns2));
                sb.append("\n");
                Log.e("net", sb.toString());
            }

        }
        return wifiInfo;
    }

    /**
     * 获取当前的网络类型
     */
    public static String getNetType(Context context) {
        String NONE = "无网络";
        String MOBILE = "手机网络";
        String WIFI = "WIFI";
        String ETHERNET = "有线网络";
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getApplicationContext()
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager == null) {
            return "无网络";
        }
//        获取当前激活的网络连接信息
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if (info == null) {
            return NONE;
        }
        int type = info.getType();

        if (type == ConnectivityManager.TYPE_MOBILE) {
            return MOBILE;
        } else if (type == ConnectivityManager.TYPE_WIFI) {
            return WIFI;
        } else if (type == ConnectivityManager.TYPE_ETHERNET) {
            return ETHERNET;
        }
        return NONE;
    }

    /**
     * Ipv4 address check.
     */
    private static final Pattern IPV4_PATTERN = Pattern.compile(
            "^(" + "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" +
                    "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");

    /**
     * Check if valid IPV4 address.
     *
     * @param input the address string to check for validity.
     * @return True if the input parameter is a valid IPv4 address.
     */
    public static boolean isIPv4Address(String input) {
        return IPV4_PATTERN.matcher(input).matches();
    }

    public static InetAddress getLocalIPAddress() {
        Enumeration<NetworkInterface> enumeration = null;
        try {
            enumeration = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException e) {
            e.printStackTrace();
        }
        if (enumeration != null) {
            while (enumeration.hasMoreElements()) {
                NetworkInterface nif = enumeration.nextElement();
                Enumeration<InetAddress> inetAddresses = nif.getInetAddresses();
                if (inetAddresses != null) {
                    while (inetAddresses.hasMoreElements()) {
                        InetAddress inetAddress = inetAddresses.nextElement();
                        if (!inetAddress.isLoopbackAddress() && isIPv4Address(inetAddress.getHostAddress())) {
                            return inetAddress;
                        }
                    }
                }
            }
        }
        return null;
    }

    /***
     * 直接获取ip,不分有线无线
     * */
    public static String getHostAddress() {
        Log.e(TAG, "getHostAddress: ");
        String hostAddress = "0.0.0.0";
        InetAddress localIPAddress = getLocalIPAddress();
        if (localIPAddress != null) {
            hostAddress = getLocalIPAddress().getHostAddress();
        }
        return hostAddress;
    }

    /**
     * 获取以太网的IP地址
     *
     * @return
     */
    public static String getEth0IpAddr() {
        String ethIp = null;
        ConnectivityManager manager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
        if (networkInfo != null) {
            Log.i("NetUtil", "NetworkInfo-->" + networkInfo.toString());
        }
        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {
            try {
                Enumeration nis = NetworkInterface.getNetworkInterfaces();
                InetAddress ia = null;
                while (nis.hasMoreElements()) {
                    NetworkInterface ni = (NetworkInterface) nis.nextElement();
                    Log.i("NetUtil", "NetworkInterface-->" + ni.toString());
                    Enumeration<InetAddress> ias = ni.getInetAddresses();
                    while (ias.hasMoreElements()) {
                        ia = ias.nextElement();
                        Log.i("NetUtil", "InetAddress-->" + ia.toString());
                        if (ia instanceof Inet6Address) {
                            continue;// skip ipv6
                        }
                        String ip = ia.getHostAddress();
                        if (!"127.0.0.1".equals(ip)) {
                            ethIp = ia.getHostAddress();
                            break;
                        }
                    }
                }
            } catch (SocketException e) {
                // Log.printErrStackTrace(TAG, e, " ");
                e.printStackTrace();
            }
        }
        return ethIp;
    }

    /**
     * 将得到的int类型的IP转换为String类型
     *
     * @param ip
     * @return
     */
    public static String intToIp(int ip) {
        return (ip & 0xFF) + "." + ((ip >> 8) & 0xFF) + "." + ((ip >> 16) & 0xFF) + "."
                + ((ip >> 24) & 0xFF);
    }

    /**
     * ip地址字符串转long型
     *
     * @param strIp
     * @return 正确返回具体的值，错误返回-1
     */
    //ip 转为整数
    public static long ipStringToLong(String strIp) {
        String[] ip = strIp.split("\\.");
        return (Long.parseLong(ip[0]) << 24) + (Long.parseLong(ip[1]) << 16) + (Long.parseLong(ip[2]) << 8) + Long.parseLong(ip[3]);
    }

    public static String longToIpString(long ip) {
        return ((ip >> 24 & 0xFF) + "." + ((ip >> 16) & 0xFF) + "." + ((ip >> 8) & 0xFF) + "." + (ip & 0xFF));
    }


    /**
     * 检查IP地址是否合法
     *
     * @param ip 要检查的IP地址
     * @return 合法返回true， 不合法返回false
     */
    public static boolean isLegalIpAddress(String ip) {
        boolean ret = false;
        if (ip != null && !ip.isEmpty()) {
            // 定义正则表达式
            String regex = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."
                    + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
                    + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
                    + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$";
            ret = ip.matches(regex);
        }

        return ret;
    }

    /**
     * 判读子网掩码的格式是否合法
     *
     * @param netmask 要判断的子网掩码
     * @return 合法返回true， 不合法返回false
     */
    public static boolean isLegalNetMask(String netmask) {
        if (netmask != null && !netmask.isEmpty()) {
            Pattern pattern = Pattern.compile("(254|252|248|240|224|192|128|0)\\.0\\.0\\.0|255\\.(254|252|248|240|224|192|128|0)\\.0\\.0|255\\.255\\.(254|252|248|240|224|192|128|0)\\.0|255\\.255\\.255\\.(255|254|252|248|240|224|192|128|0)|^[1-9]$|^2\\d$|^3[0-2]$");
            return pattern.matcher(netmask).matches();
        }

        return false;
    }

    /**
     * 检查设置的服务器地址是否合法
     *
     * @param address
     * @return
     */
    public static boolean isLegalServerAddress(final String address) {
        final String baseRegex = "[\\w\\-_]+(\\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?";
        String regex = baseRegex;
        if (address.contains("http")) {
            regex = "(http|ftp|https)://" + baseRegex;
        }
        Pattern p = Pattern.compile(regex);
        return p.matcher(address).find();
    }

    /**
     * 根据IP地址生成子网掩码
     *
     * @param ip
     * @return
     */
    public static String createNetMask(final String ip) {
        String netmask = null;
        if (ip != null && !ip.isEmpty()) {
            String[] arrays = ip.split("\\.");
            if (arrays != null && arrays.length > 0) {
                int firstValue = Integer.parseInt(arrays[0]);
                if (firstValue <= 127)
                    netmask = "255.0.0.0";//A
                else if (firstValue <= 191)
                    netmask = "255.255.0.0";//B
                else if (firstValue <= 223)
                    netmask = "255.255.255.0";//C
            }
        }

        return netmask;
    }

    public static String createGateway(final String ip, final String netmask) {
        String gateway = null;
        if ((ip != null && !ip.isEmpty()) &&
                (netmask != null && !netmask.isEmpty())) {
            //有效，才推算
            long nIp = NetUtil.ipStringToLong(ip);
            long nMask = NetUtil.ipStringToLong(netmask);
            long nGate = (nIp & nMask) + 1;
            gateway = NetUtil.longToIpString(nGate);
        }

        return gateway;
    }

    private static final String ETH0_MAC_ADDR = "/sys/class/net/eth0/address";
    private static final String WLAN0_MAC_ADDR = "/sys/class/net/wlan0/address";
    public static final String MAC_ERROR = "unavailable";

    /**
     * 获取以太网的mac地址
     *
     * @return
     */
    public static String getEthMacAddress() {
        try {
            return readLine(ETH0_MAC_ADDR);
        } catch (IOException e) {
            // Log.printErrStackTrace(TAG, e, "");
            e.printStackTrace();
            return MAC_ERROR;
        }
    }

    /**
     * 获取WiFi的mac地址
     *
     * @return
     */
    public static String getWlanMacAddress() {
        try {
            return readLine(WLAN0_MAC_ADDR);
        } catch (IOException e) {
            // Log.printErrStackTrace(TAG, e, "");
            e.printStackTrace();
            return MAC_ERROR;
        }
    }

    private static String readLine(String filename) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(filename), 256);
        try {
            return reader.readLine();
        } finally {
            reader.close();
        }
    }

    public static final int UNKNOWN_NETWORK_TYPE = 0;
    public static final int ETHERNET_NETWORK_TYPE = 1;
    public static final int WIFI_NETWORK_TYPE = 2;

    public static int getConnectedNetworkType() {
        ConnectivityManager manager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
        if (networkInfo != null) {
            Log.i("NetUtil", "NetworkInfo-->" + networkInfo.toString());
            if (networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {
                return ETHERNET_NETWORK_TYPE;
            } else if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                return WIFI_NETWORK_TYPE;
            }
        }

        return UNKNOWN_NETWORK_TYPE;
    }

    public class ConnectedWifiInfo {
        private String ssid; // Wifi源名称
        private int speed; // 链接速度
        private String units; // 链接速度单位
        private int strength;//链接信号强度

        private DhcpInfo dhcpInfo;

        public String getSsid() {
            return ssid;
        }

        public DhcpInfo getDhcpInfo() {
            return dhcpInfo;
        }

        public void setDhcpInfo(DhcpInfo dhcpInfo) {
            this.dhcpInfo = dhcpInfo;
        }

        public void setSsid(String ssid) {
            this.ssid = ssid;
        }

        public int getSpeed() {
            return speed;
        }

        public void setSpeed(int speed) {
            this.speed = speed;
        }

        public String getUnits() {
            return units;
        }

        public void setUnits(String units) {
            this.units = units;
        }

        public int getStrength() {
            return strength;
        }

        public void setStrength(int strength) {
            this.strength = strength;
        }

        @Override
        public String toString() {
            return "ConnectedWifiInfo{" +
                    "ssid='" + ssid + '\'' +
                    ", speed=" + speed +
                    ", units='" + units + '\'' +
                    ", strength=" + strength +
                    ", dhcpInfo=" + dhcpInfo +
                    '}';
        }
    }

}
